#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "packet.h"
#include "server.h"
#include "controller.h"
#include "teaint.h"

int main(int argc, char *argv[])
{
  int opt;

  int cnum = -1;
  char *host = "127.0.0.1";
  int port = 9090;
  int emu_time_err = 0;
  int phase_delay = 15;
  char *key = NULL;

  while ((opt = getopt(argc, argv, "n:h:p:ed:k:")) != -1)
  {
    switch (opt) 
    {
      case 'n':
        cnum = atoi(optarg);
      break;
      
      case 'h':
      	if (optarg != NULL)
      	{
      		host = strdup(optarg);
      	}
      break;
      
      case 'p':
      	port = atoi(optarg);
      break;

      case 'd':
      	phase_delay = atoi(optarg);
      break;
      
      case 'e':
      	emu_time_err = 1;
      break;
      
      case 'k':
      	if (optarg != NULL)
      	{
      		key = strdup(optarg);
      	}
      break;	

      default: /* '?' */
        fprintf(stderr, "Usage: %s -n cnum -k key [-h host] [-p port] [-e] [-d delay]  \n", argv[0]);
        return 200;
    }
  }
  
  if (cnum == -1)
  {
  	fprintf(stderr,"Set controller number by -n option\n");
  	return 200;
  }
  
  if (key == NULL)
  {
  	fprintf(stderr,"Set controller key !\n");
  	return 200;
  }
  else
  {
  	if (tea_create(key) != 0)
  	{
  		printf(">>> Start with key: %s\n", key);
  	}
  	else
  	{
  		fprintf(stderr,"Can not parse key !\n");
  		return 200;
  	}
  }

  printf(">>> Connect to server %s:%d with controller number: %d\n", host, port, cnum);
  int sock = connect_to_server(host , port);

  if (sock < 0)
  {
	perror("Can't connect to server");	
	return 200;
  }
  
  printf(">>> Successful connect to server!\n");
  
  if (greet_with_server(sock, cnum) < 0)
  {
	perror("Can't greet with server");
	close(sock);
	return 200;
  }
  
  controller_t cont;
  
  cont.controller_num_ = cnum;
  cont.current_phase_ = 0;
  cont.time_error_ = emu_time_err;
  cont.phase_delay_ = phase_delay;

  while(1)
  {
	  size_t max_buf_size = 256;
	  char read_buffer[max_buf_size];
	  memset(read_buffer, 0, max_buf_size);

	  int size_rx = read(sock, read_buffer, max_buf_size);

	  if (size_rx < 0)
	  {
		perror("Can't read");
		break;
	  }
	  else if (size_rx == 0)
	  {
		break;
	  }

      printf("Raw read buffer:");
  	  dump_packet(read_buffer, size_rx);
  	  printf("\n");
  	  
  	  tea_decode(read_buffer, size_rx);

  	  printf("Dec read buffer:");
  	  dump_packet(read_buffer, size_rx);
  	  printf("\n");

	  const unsigned char *dst;
	  unsigned int dstlen;

	  if (parse_packet(read_buffer, max_buf_size, &dst , &dstlen) < 0) 
	  {
		printf("Can't parse packet!\n");
		break;
	  }
	  
	  const int buf_len = 32;
	  
	  char out[buf_len];
	  
	  size_t real_len;
	  
	  if (controller_exec_command(&cont, dst, dstlen, out, buf_len, &real_len))
	  {
	  
	   	printf("     Build buffer:");
  		dump_packet(out, real_len);
  		printf("\n");

	   	printf(" Raw write buffer:");
  		dump_packet(out, buf_len);
  		printf("\n");

		tea_encode(out, buf_len);

	   	printf("Real write buffer:");
  		dump_packet(out, buf_len);
  		printf("\n");

	  	if (write(sock, out, buf_len) == 0)
	  	{
	  		printf("Remote side close connection !\n");
	  		break;
	  	}
	  }
	  else
	  {
		printf("Invalid command !\n");
		break;
	  }

  }

  close(sock);

}
